﻿using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Publicuse.Util.Redis
{
    /// <summary>
    /// Redis操作数据辅助
    /// </summary>
    public static class ServiceStackUtil
    {
        /// <summary>
        /// Redis业务操作
        /// </summary>
        /// <param name="conIndex"></param>
        /// <param name="dbIndex"></param>
        /// <param name="msg"></param>
        /// <param name="action"></param>
        public static void DoAction(int conIndex, int dbIndex, out string msg, Action<IRedisClient> action)
        {
            msg = string.Empty;
            try
            {
                using (var dbClient = ServiceStackManager.GetRedisManager.GetClient(conIndex, dbIndex))
                {
                    action.Invoke(dbClient);
                }
            }
            catch (Exception ex)
            {
                //LogUtil.GetInstance.WriteLogOld("Redis操作", ex.Message + "|" + ex.StackTrace, false);
                msg = ex.Message;
            }
        }

        /// <summary>
        /// 获取Hash所有的数据转换为字典集合
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetHashToDictionaryByKey(this IRedisClient client, string key)
        {
            return client?.GetAllEntriesFromHash(key);
        }

        /// <summary>
        /// 获取Hash所有数据转换为实体对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T GetHashToObjectByKey<T>(this IRedisClient client, string key) where T : new()
        {
            var list = client?.GetAllEntriesFromHash(key);
            return JsonUtil.DicToObject<T>(list);
        }

        /// <summary>
        /// 获取Hash对应多个Key对应的值
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="names"></param>
        /// <returns></returns>
        public static List<string> GetHashMoreByKeys(this IRedisClient client, string key, string[] names)
        {
            return client?.GetValuesFromHash(key, names);
        }

        /// <summary>
        ///获取Hash对应Key对应值
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string GetHashValuByKey(this IRedisClient client, string key, string name)
        {
            return client?.GetValueFromHash(key, name);
        }

        /// <summary>
        /// 获取Hash包含特定字符的集合
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetHashValuLikeKey(this IRedisClient client, string key, string value)
        {
            Dictionary<string, string> list = new Dictionary<string, string>();
            IEnumerable<KeyValuePair<string, string>> keyValuePair = null;
            if (!string.IsNullOrEmpty(value))
            {
                keyValuePair = client?.ScanAllHashEntries(key, "*" + value + "*");
            }
            else
            {
                keyValuePair = client?.ScanAllHashEntries(key);
            }
            foreach (var item in keyValuePair)
            {
                list.Add(item.Key, item.Value);
            }
            return list;
        }

        /// <summary>
        ///  获取SortedSet包含特定字符的集合
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Dictionary<string, double> GetSortSetLikeKey(this IRedisClient client, string key, string value)
        {
            Dictionary<string, double> list = new Dictionary<string, double>();
            IEnumerable<KeyValuePair<string, double>> keyValuePair = null;
            if (!string.IsNullOrEmpty(value))
            {
                keyValuePair = client?.ScanAllSortedSetItems(key, "*" + value + "*");
            }
            else
            {
                keyValuePair = client?.ScanAllSortedSetItems(key);
            }
            foreach (var item in keyValuePair)
            {
                list.Add(item.Key, item.Value);
            }
            return list;
        }

        /// <summary>
        ///  获取Set包含特定字符的集合
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static List<string> GetSetLikeKey(this IRedisClient client, string key, string value)
        {
            List<string> list = new List<string>();
            IEnumerable<string> keyValuePair = null;
            if (!string.IsNullOrEmpty(value))
            {
                keyValuePair = client?.ScanAllSetItems(key, "*" + value + "*");
            }
            else
            {
                keyValuePair = client?.ScanAllSetItems(key);
            }
            foreach (var item in keyValuePair)
            {
                list.Add(item);
            }
            return list;
        }


        /// <summary>
        /// 获取Hash某个Key的数量
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static long GetHashLengthByKey(this IRedisClient client, string key)
        {
            if (client == null)
                return 0;

            return client.GetHashCount(key);
        }

        /// <summary>
        /// 插入对象到Hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="trans"></param>
        /// <param name="key"></param>
        /// <param name="suit"></param>
        public static void AddDbjectToHash<T>(this IRedisClient client, string key, T suit) where T : new()
        {
            Dictionary<string, string> keyValuePairs = RedisTools.ObjectToDictionary(suit);
            client?.SetRangeInHash(key, keyValuePairs);
        }

        /// <summary>
        /// 插入单个值到Hash
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public static void AddHashValueByKey(this IRedisClient client, string key, string name, string value)
        {
            client?.SetEntryInHash(key, name, value);
        }

        /// <summary>
        /// 判断Hash某个Key是否存在
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="name"></param>
        public static bool HashExists(this IRedisClient client, string key, string name)
        {
            if (client == null)
                return false;

            return client.HashContainsEntry(key, name);
        }

        /// <summary>
        /// 判断Set某个Key是否存在
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool SetExists(this IRedisClient client, string key, string name)
        {
            return client?.GetSetCount(key) > 0;
        }

        /// <summary>
        /// 插入多个值到Hash
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="keyValues"></param>
        public static void AddHashValuesByKey(this IRedisClient client, string key, Dictionary<string, string> keyValues)
        {
            client?.SetRangeInHash(key, keyValues);
        }

        /// <summary>
        ///  如果hashid集合中存在key/value则不添加返回false，
        ///  如果不存在在添加key/value,返回true
        /// </summary>
        /// <param name="client"></param>
        /// <param name="hashid"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static bool AddHashValueByKeyNotExists(this IRedisClient client, string hashid, string key, string value)
        {
            if (client == null)
                return false;

            return client.SetEntryInHashIfNotExists(hashid, key, value);
        }

        /// <summary>
        /// 修改Hash对应Key的Value加1
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public static void AddHashValuesByKeyAdd(this IRedisClient client, string key, string name, int value = 1)
        {
            client?.IncrementValueInHash(key, name, value);
        }

        /// <summary>
        /// 修改Hash对应Key的Value加1
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public static void AddHashValuesByKeyAdd(this IRedisClient client, string key, string name, long value = 1)
        {
            client?.IncrementValueInHash(key, name, value);
        }

        /// <summary>
        /// 移除Hash对应Key对应值
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="name"></param>
        public static void DeleteHashValueByKey(this IRedisClient client, string key, string name)
        {
            client?.RemoveEntryFromHash(key, name);
        }

        /// <summary>
        /// 移除有序集合对应Key对应值
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="name"></param>
        public static void DeleteSortedSetValueByKey(this IRedisClient client, string key, string name)
        {
            client?.RemoveItemFromSortedSet(key, name);
        }

        /// <summary>
        /// 插入数据到Sorted
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void AddSet(this IRedisClient client, string key, string value)
        {
            client?.AddItemToSet(key, value);
        }

        /// <summary>
        /// 插入多条数据到Sorted
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="values"></param>
        public static void AddSets(this IRedisClient client, string key, List<string> values)
        {
            client?.AddRangeToSet(key, values);
        }

        /// <summary>
        /// 插入数据到SortedSet
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="time"></param>
        public static void AddSortedSet(this IRedisClient client, string key, string value, long time)
        {
            client?.AddItemToSortedSet(key, value, time);
        }

        /// <summary>
        ///  插入数据到SortedSet
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="score"></param>
        public static void AddSortedSet(this IRedisClient client, string key, string value, double score)
        {
            client?.AddItemToSortedSet(key, value, score);
        }

        /// <summary>
        ///  插入数据到SortedSet
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void AddSortedSet(this IRedisClient client, string key, string value)
        {
            client?.AddItemToSortedSet(key, value);
        }

        /// <summary>
        /// 插入多条数据到SortedSet
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="values"></param>
        /// <param name="time"></param>
        public static void AddSortedSets(this IRedisClient client, string key, List<string> values, double time)
        {
            client?.AddRangeToSortedSet(key, values, time);
        }

        /// <summary>
        /// 判断某个Key信息是否存在
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool KeyExists(this IRedisClient client, string key)
        {
            if (client == null)
                return false;

            return client.ContainsKey(key);
        }

        /// <summary>
        /// 设置过期时间
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="timeSpan"></param>
        public static void SetKeyExpire(this IRedisClient client, string key, TimeSpan timeSpan)
        {
            client?.ExpireEntryIn(key, timeSpan);
        }

        /// <summary>
        /// 插入数据到队列
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="jsonData"></param>
        public static void AddDataToQueue(this IRedisClient client, string key, string jsonData)
        {
            client?.EnqueueItemOnList(key, jsonData);
        }

        /// <summary>
        ///从队列获取数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetDataFromQueue(this IRedisClient client, string key)
        {
            return client?.DequeueItemFromList(key);
        }

        /// <summary>
        /// 获取队列数据总数
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static long GetDataFromQueueLength(this IRedisClient client, string key)
        {
            if (client == null)
                return 0;

            return client.GetListCount(key);
        }

        /// <summary>
        /// 获取队列一条数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetDataFromQueueOne(this IRedisClient client, string key)
        {
            return client?.PopItemFromList(key);
        }

        /// <summary>
        /// 获取队列里面所有的数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static List<string> GetDataFromQueueList(this IRedisClient client, string key)
        {
            return client?.GetAllItemsFromList(key);
        }

        /// <summary>
        /// 获取SortedSet所有信息
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static List<string> GetAllSortSetList(this IRedisClient client, string key)
        {
            return client?.GetAllItemsFromSortedSetDesc(key);
        }

        /// <summary>
        /// 获取SortedSet指定条数信息，倒叙排序
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="sortType"></param>
        /// <returns></returns>
        public static List<string> GetAllSortSetList(this IRedisClient client, string key, int start, int end, int sortType)
        {
            if (sortType == 1)
                return client?.GetRangeFromSortedSet(key, start, end);
            else
                return client?.GetRangeFromSortedSetDesc(key, start, end);
        }

        /// <summary>
        /// 移除某个Key数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        public static void DeleteDataByKey(this IRedisClient client, string key)
        {
            client?.Remove(key);
        }

        /// <summary>
        /// 删除多个Key数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="keys"></param>
        public static void DeleteDatasByKey(this IRedisClient client, string[] keys)
        {
            client?.RemoveAll(keys);
        }

        /// <summary>
        /// 移除Set某个Key数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void DeleteSetByKey(this IRedisClient client, string key, string value)
        {
            client?.RemoveItemFromSet(key, value);
        }

        /// <summary>
        /// 获取所有的Set数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static List<string> GetSetAll(this IRedisClient client, string key)
        {
            List<string> list = new List<string>();
            var ls = client?.GetAllItemsFromSet(key);
            foreach (var item in ls)
            {
                list.Add(item.ToString());
            }
            return list;
        }


        /// <summary>
        /// 插入单个数据到String
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void AddStringData(this IRedisClient client, string key, string value)
        {
            client?.AppendToValue(key, value);
        }

        /// <summary>
        /// 插入多个数据到String
        /// </summary>
        /// <param name="client"></param>
        /// <param name="list"></param>
        public static void AddStringDatas(this IRedisClient client, Dictionary<string, string> list)
        {
            client?.SetAll(list);
        }

        /// <summary>
        /// 获取Stirng的值
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetDataFromString(this IRedisClient client, string key)
        {
            return client?.GetValue(key);
        }

        /// <summary>
        /// 提交事务捕获异常
        /// </summary>
        /// <param name="transaction"></param>
        /// <returns></returns>
        public static bool CommitTransac(this IRedisTransaction transaction)
        {
            if (!transaction.Commit())
            {
                transaction.Rollback();
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 更换Redis索引库,默认是0号索引库
        /// </summary>
        /// <param name="client"></param>
        /// <param name="newDb"></param>
        /// <returns></returns>
        public static IRedisClient ChangeDB(this IRedisClient client, int newDb)
        {
            if (client == null)
                return null;

            client.Db = newDb;
            return client;
        }

        /// <summary>
        /// 发布订阅
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="message"></param>
        /// <param name="msg"></param>
        public static void Publishsubscribe(this IRedisClient client, string key, string message)
        {
            client?.PublishMessage(key, message);
        }

        /// <summary>
        /// 取消要发布的订阅
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="msg"></param>
        public static void Cancelsubscription(this IRedisClient client, string key)
        {
            var subscription = client?.CreateSubscription();
            subscription.UnSubscribeFromChannels(key);
        }

        /// <summary>
        /// 订阅
        /// </summary>
        /// <param name="client"></param>
        /// <param name="key"></param>
        /// <param name="actionOnMessage"></param>
        /// <param name="msg"></param>
        public static void Subscribe(this IRedisClient client, string key, Action<string, string, IRedisSubscription> actionOnMessage)
        {
            var subscription = client?.CreateSubscription();
            subscription.OnSubscribe = c =>
            {
                Console.WriteLine($"订阅频道{c}");
                Console.WriteLine();
            };
            //取消订阅
            subscription.OnUnSubscribe = c =>
            {
                Console.WriteLine($"取消订阅 {c}");
                Console.WriteLine();
            };
            subscription.OnMessage += (c, s) =>
            {
                actionOnMessage(c, s, subscription);
            };
            subscription.SubscribeToChannels(key); //blocking
        }

    }
}
